#include "generador_de_relaciones.h"

#include <iostream>

bool GeneradorDeRelaciones::elDescriptorEsSiempre(Lista<Alumno*>* alumnos, DescriptorAlumno descriptor, bool valor) {

	IteradorLista<Alumno*> iterador = alumnos->iterador();
	while(iterador.tieneSiguiente()){
		if(iterador.siguiente()->getValorDelDescriptor(descriptor) != valor){
			return false;
		}
	}

	return true;
}

void GeneradorDeRelaciones::limpiarDescriptores(Lista<Alumno*>* alumnos, ConjuntoDeDescriptores &descriptores){

	IteradorConjuntoDeDescriptores iterador = descriptores.iterador();

	while(iterador.tieneSiguiente()){
		if(this->elDescriptorEsSiempre(alumnos, iterador.get(), true) || this->elDescriptorEsSiempre(alumnos, iterador.get(), false)){
			descriptores.quitarDescriptor(iterador.siguiente());
		}else{
			iterador.siguiente();
		}
	}

}

bool GeneradorDeRelaciones::mayoriaConPromedioSobreCuatro(Lista<Alumno*>* alumnos){

	int cantidadVerdadero = 0;
	int cantidadFalso = 0;

	IteradorLista<Alumno*> iterador = alumnos->iterador();
	while(iterador.tieneSiguiente()){
		if(iterador.siguiente()->getPromedioMayorACuatro()){
			cantidadVerdadero++;
		}else{
			cantidadFalso++;
		}
	}

	return cantidadVerdadero > cantidadFalso;
}

NodoArbolBinario<DescriptorAlumno>* GeneradorDeRelaciones::generarArbolDeRelaciones(Lista<Alumno*>* alumnos,
		DescriptorAlumno calificador, ConjuntoDeDescriptores descriptores) {

	NodoArbolBinario<DescriptorAlumno>* nuevoNodo = new NodoArbolBinario<DescriptorAlumno>;

	if(this->elDescriptorEsSiempre(alumnos, calificador, true)){
		nuevoNodo->setDato(calificador);
		nuevoNodo->setHijoIzquierdo(0);
		nuevoNodo->setHijoDerecho(nuevoNodo);

		return nuevoNodo;
	}

	if(this->elDescriptorEsSiempre(alumnos, calificador, false)){
		nuevoNodo->setDato(calificador);
		nuevoNodo->setHijoIzquierdo(nuevoNodo);
		nuevoNodo->setHijoDerecho(0);

		return nuevoNodo;
	}

	/**
	 * Se eliminan los descriptores que no aportan nada al arbol
	 * de relaciones.
	 */
	this->limpiarDescriptores(alumnos, descriptores);

	if(descriptores.tamanio() == 0){
		nuevoNodo->setDato(calificador);
		if(this->mayoriaConPromedioSobreCuatro(alumnos)){
			nuevoNodo->setHijoIzquierdo(0);
			nuevoNodo->setHijoDerecho(nuevoNodo);
		}else{
			nuevoNodo->setHijoIzquierdo(nuevoNodo);
			nuevoNodo->setHijoDerecho(0);
		}

		return nuevoNodo;
	}

	CalculadorDeGanancia calculador;
	DescriptorAlumno mejorDescriptor = calculador.descriptorConMayorGanancia(alumnos, descriptores);
	descriptores.quitarDescriptor(mejorDescriptor);
	nuevoNodo->setDato(mejorDescriptor);

	ClasificadorDeAlumnosPorDescriptor clasificador;
	ClasificacionDeAlumnosPorDescriptor *clasificacion = clasificador.clasificarAlumnos(alumnos, mejorDescriptor);
	if(clasificacion->getListaFalso()->estaVacia() == false){
		nuevoNodo->setHijoIzquierdo(this->generarArbolDeRelaciones(clasificacion->getListaFalso(), calificador, descriptores));
	}else{
		nuevoNodo->setHijoIzquierdo(0);
	}

	if(clasificacion->getListaVerdadero()->estaVacia() == false){
		nuevoNodo->setHijoDerecho(this->generarArbolDeRelaciones(clasificacion->getListaVerdadero(), calificador, descriptores));
	}else{
		nuevoNodo->setHijoDerecho(0);
	}

	delete clasificacion;

	return nuevoNodo;
}


Resultado GeneradorDeRelaciones::generarRelaciones(Lista<Alumno*>* alumnos,
		DescriptorAlumno calificador, ConjuntoDeDescriptores descriptores) {

	Resultado elResultado;


	ArbolBinario<DescriptorAlumno>* arbol = new ArbolBinario<DescriptorAlumno>;
	arbol->setRaiz(this->generarArbolDeRelaciones(alumnos, calificador, descriptores));


	elResultado.setArbolDeRelaciones(arbol);


	return elResultado;
}
